package com.runa.rccprotocol.analysis;

import com.alibaba.fastjson.JSON;
import com.runa.monitor.comm.dto.Valve;
import com.runa.monitor.comm.entity.CommValve;
import com.runa.persistence.task.RequestPendingTask;
import com.runa.persistence.task.TaskTypeEnum;
import com.runa.persistence.util.LogUtil;
import com.runa.protocol.analysis.MetaBufferAnalysis;
import com.runa.protocol.analysis.ShellBufferAnalysis;
import com.runa.protocol.dto.IInterData;
import com.runa.protocol.enums.ByteOrder;
import com.runa.protocol.util.ByteUtil;
import com.runa.rccprotocol.analysis.hanyang.HyAnalysis;
import com.runa.rccprotocol.analysis.kute.KtAnalysis;
import com.runa.rccprotocol.analysis.pusai.PsAnalysis;
import com.runa.rccprotocol.analysis.rn.RunaBuildValveAnalysis;
import com.runa.rccprotocol.analysis.wukexing.WkxAnalysis;
import com.runa.rccprotocol.constant.AppFunCode;
import com.runa.rccprotocol.dto.ConcentratorElectric;
import com.runa.rccprotocol.dto.ConcentratorResponseData;
import com.runa.rccprotocol.dto.generic.OriginalConcenRequestData;
import com.runa.rccprotocol.dto.generic.OriginalConcenResponseData;
import com.runa.rccprotocol.dto.runa.*;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;

import static com.runa.rccprotocol.dto.runa.RunaFrameSequence.fn;
import static com.runa.rccprotocol.dto.runa.RunaFrameSequence.pn;

/**
 * @author zhuj
 * 瑞纳集中器解析器（外层）
 */
@Slf4j
public class RunaICAnalysis extends ShellBufferAnalysis<byte[]> {

    public RunaICAnalysis(MetaBufferAnalysis analysis) {
        super(analysis, 0);
    }


    @Override
    public int fill(byte[] data, int length, String n) {
        log.debug("瑞纳解码: {} {}", ByteUtil.byteToHexStringTrim(data), length);
        interData = null;
        if (length < 6) {
            return -1;
        }
        int begin;
        for (begin = 0;begin < length;begin++) {
            if ((data[begin]&0xff) == 0x68
                    && data[begin+5] == 0x68) {
                break;
            }
        }
        int L = (((data[begin+1]&0xff)) + (data[begin+2]<<8)) >> 2;
        if (length < L + 8) {
            return -1;
        }
        //(data[begin+L+6]&0xff) == 0x68 &&
        else if (data[begin+6+L] == ByteUtil.sum(data, begin+6, L)){
            RunaICStruct struct = new RunaICStruct();
            //控制域
            struct.setControl(new RunaFrameSequence.Control(data[begin+6]));
            //地址域
            struct.setArea(new RunaFrameSequence.Area(data, begin+7));
            //应用层功能码
            struct.setAfn(AppFunCode.rnicAFN.valueOf(data[begin+12] & 0xff));
            //帧序列域SEQ
            struct.setSeq(new RunaFrameSequence.Seq(data[begin+13]));
            if (OriginalConcenRequestData.isOriginal(struct.getArea().toString())) {
                interData = new OriginalConcenResponseData(data, begin, L+8);
//                netEquNo = struct.getArea().toString();
                ((OriginalConcenResponseData)interData).setAddress(struct.getArea().toString());
            } else {
                //begin+14:数据单元起始点，L:用户数据长度
                linkUserData(struct, data, begin + 14, L);
                if (this.interData instanceof ConcentratorResponseData) {
                    ((ConcentratorResponseData<?>) this.interData).setTailFrame(struct.getSeq().endFrame());
                }
            }
        }
        return length - L - 8;
    }

    private void linkUserData(RunaICStruct struct, byte[] data, int offset, int dLen) {
        //TpV为1时，携带AUX，需减去这段字节
        dLen = struct.getSeq().TpV == 1 ? dLen-8 : dLen;
        switch (struct.getAfn()) {
            case AffirmDeny:
//                int pn = pn(data[offset], data[offset+1]);
                int fn = fn(data[offset+2], data[offset+3]);
                if (fn == 1 || fn == 3) {
                    interData = new RunaConcenAffirmDeny(struct.getArea().toString(), true);
                } else if (fn == 2) {
                    interData = new RunaConcenAffirmDeny(struct.getArea().toString(), false);
                }
                break;
            case LinkInterfaceDetect:
                int pn = pn(data[offset], data[offset+1]);
                fn = fn(data[offset+2], data[offset+3]);
                if (pn == 0 && fn == 1) {
                    // 登录
                    netEquNo = struct.getArea().toString();
                    LogUtil.linkDetect(netEquNo, "瑞纳", data, offset - 8 + dLen, "登录");
                    interData = new RunaConcentratorRegister(struct);
                }
                if (pn == 0 && fn == 3) {
                    // 心跳
                    netEquNo = struct.getArea().toString();
                    LogUtil.linkDetect(netEquNo, "瑞纳", data, offset - 8 + dLen, "心跳");
                    interData = new RunaConcentratorHeart(struct);
                }
                if (pn == 0 && fn == 4) {
                    ConcentratorElectric electric = new ConcentratorElectric(struct.getArea().toString());
                    electric.setMustAck(true);
                    electric.setAck(new RunaFmuDataAck(struct.getArea(), struct.getSeq().RSEQ_PSEQ));
                    electric.setReportData(((RunaEquDataAnalysis)analysis).concenReportData(data, offset+6));
                    interData = electric;
                }
                break;
            case ReqTerminalConfig:
                pn = pn(data[offset], data[offset + 1]);
                fn = fn(data[offset + 2], data[offset + 3]);
                if (pn == 0 && fn == 1) {
                    // 终端配置（版本信息）
                    byte[] afn09f1 = new byte[32];
                    System.arraycopy(data, offset+4, afn09f1, 0, afn09f1.length);
                    RunaFrameSequence.DataUnit unit = new RunaFrameSequence.DataUnit(pn, fn, afn09f1);
                    struct.addDataField(unit);
                    analysis.fill(struct, 0, netEquNo);
                    interData = analysis.gain();
                }
                break;
            case QueryParam:
                RunaFrameSequence.DataUnit dataUnit;
                AtomicInteger beginRef = new AtomicInteger(offset);
                while ((dataUnit = structUnitParam(data, beginRef, dLen)) != null) {
                    struct.addDataField(dataUnit);
                }
                analysis.fill(struct, 0, netEquNo);
                interData = analysis.gain();
                break;
            case RequestDataOne:
                // 处理实时数据
                beginRef = new AtomicInteger(offset);
                while ((dataUnit = structUnitDataOne(data, beginRef, offset + dLen - 8)) != null) {
                    struct.addDataField(dataUnit);
                }
                analysis.fill(struct, 0, netEquNo);
                interData = analysis.gain();
                break;
            case RequestDataTwo:
                // 处理历史数据
                beginRef = new AtomicInteger(offset);
                while ((dataUnit = structUnitDataTwo(data, beginRef, dLen)) != null) {
                    struct.addDataField(dataUnit);
                }
                analysis.fill(struct, 0, netEquNo);
                interData = analysis.gain();
                break;
            case RequestDataThree:
                // 处理事件数据
                pn = pn(data[offset], data[offset+1]);
                fn = fn(data[offset+2], data[offset+3]);
                if (fn == 3) {
                    int count = (data[offset+10] + (data[offset+11]<<8)) - (data[offset+8] + (data[offset+9]<<8));
                    if (count < 0) {
                        count = 1152 + count;
                    }
                    int index = 12;
                    for (int i=0; i<count; i++) {
                        int le = data[offset + index + 10]&0x0f;
                        byte[] event = new byte[11 + le];
                        System.arraycopy(data, offset+index+11, event, 0, event.length);
                        struct.addDataField(new RunaFrameSequence.DataUnit(pn, fn, event));
                        index += (le + 11);
                    }
                    analysis.fill(struct, 0, netEquNo);
                    interData = analysis.gain();
                }
                break;
            case DataForward:
                //TODO 数据转发应答
                String netSerial = struct.getArea().toString();
                TaskTypeEnum taskType = RequestPendingTask.getTaskType(netSerial);
                if (null != taskType) {
                    pn = pn(data[offset], data[offset+1]);
                    fn = fn(data[offset+2], data[offset+3]);
                    if (pn == 0 && fn == 1) {
                        int len = data[offset + 5] + (data[offset + 6] << 8);
                        byte[] bs = new byte[len];
                        System.arraycopy(data, offset + 7, bs, 0, bs.length);
                        switch (taskType) {
                            case READ_WKX_VALVE:
                            case WRITE_WKX_VALVE:
                                WkxAnalysis wkxAnalysis = new WkxAnalysis();
                                wkxAnalysis.handleWkxValve(bs, 0, bs.length);
                                this.interData = wkxAnalysis.getInterData();
                                break;
                            case READ_KT_VALVE:
                            case WRITE_KT_VALVE:
                                KtAnalysis ktAnalysis = new KtAnalysis();
                                ktAnalysis.valveHandle(bs, 0, bs.length);
                                this.interData = ktAnalysis.getInterData();
                                break;
                            case READ_HY_METER:
                                HyAnalysis hyAnalysis = new HyAnalysis();
                                hyAnalysis.handleData(bs, 0, bs.length);
                                this.interData = hyAnalysis.getInterData();
                                break;
                            case READ_PS_VALVE:
                            case WRITE_PS_VALVE:
                                PsAnalysis psAnalysis = new PsAnalysis();
                                psAnalysis.valveHandle(bs, 0, bs.length);
                                this.interData = psAnalysis.getInterData();
                                break;
                            case READ_RN_MODBUS_VALVE:
                                RunaBuildValveAnalysis runaValveAnalysis = new RunaBuildValveAnalysis();
                                runaValveAnalysis.handleModbusData(netSerial, bs, 0, bs.length);
                                this.interData = runaValveAnalysis.getInterData();
                                break;

                        }
                        if (this.interData instanceof RunaConcenResponseData) {
                            RunaConcenResponseData responseData = (RunaConcenResponseData)this.interData;
                            responseData.setAddress(struct.getArea().toString());
                            responseData.setCommand(struct.getAfn());
                        } else if (this.interData instanceof RunaConcenAffirmDeny) {
                            RunaConcenAffirmDeny affirmDeny = (RunaConcenAffirmDeny)this.interData;
                            affirmDeny.setAddress(struct.getArea().toString());
                        }
                    }
                } else {
                    int index = 0;
                    pn = pn(data[offset+index], data[offset+index+1]);
                    fn = fn(data[offset+index+2], data[offset+index+3]);
                    if (fn != 1) {
                        break;
                    }
                    int k = data[offset+index+5] + (data[offset+index+6]<<8);
                    byte[] bs = new byte[3+k];
                    System.arraycopy(data, offset+index+4, bs, 0, bs.length);
                    struct.addDataField(new RunaFrameSequence.DataUnit(pn, fn, bs));
                    analysis.fill(struct, 0, netEquNo);
                    interData = analysis.gain();
                }
                break;
            default:
        }
    }

    private RunaFrameSequence.DataUnit structUnitParam(byte[] buffer, AtomicInteger beginRef, int len) {
        int begin = beginRef.get();
        if (buffer.length - begin < 6) {
            return null;
        }
        int pn = pn(buffer[begin], buffer[begin+1]);
        int fn = fn(buffer[begin+2], buffer[begin+3]);
        RunaFrameSequence.DataUnit dataUnit = null;

        switch (fn) {
            case 1:
                byte[] bs;
                if (len - begin >= 4) {
                    bs = new byte[6];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 9:
            case 192:
                if (len - begin >= 14) {
                    bs = new byte[16];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 3:
                if (len - begin >= 26) {
                    bs = new byte[28];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 84:
            case 194:
                if (len - begin >= 126) {
                    bs = new byte[128];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 7:
                if (len - begin >= 24) {
                    try {
                        int m = buffer[begin+4+21];
                        int n = buffer[22+m];
                        int zc = 24 + m + n;
                        if (len - begin > zc - 2) {
                            bs = new byte[zc];
                            System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                            beginRef.addAndGet(bs.length+4);
                        }
                    } catch (Exception e) {
                        break;
                    }
                }
                break;
            case 193:
                if (len - begin >= 10) {
                    bs = new byte[12];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 85:
            case 216:
                if (len - begin >= 4) {
                    bs = new byte[6];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 91:
                if (len >= begin) {
                    int zc = 2 + (buffer[begin+4] + (buffer[begin+5]<<8)) * 22;
                    if (len - begin >= zc - 2) {
                        bs = new byte[zc];
                        System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                        beginRef.addAndGet(bs.length+4);
                    }
                }
                break;
            case 92:
                if (len - begin >= 18) {
                    bs = new byte[20];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 100:
            case 191:
                if (len - begin >= 2) {
                    bs = new byte[4];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 210:
                if (len >= begin - 1) {
                    int zc = 1 + buffer[begin+4] * 37;
                    if (len - begin >= zc - 2) {
                        bs = new byte[zc];
                        System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                        beginRef.addAndGet(bs.length+4);
                    }
                }
                break;
            case 211:
                if (len - begin >= 5) {
                    bs = new byte[7];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 212:
                if (len >= begin - 1) {
                    int zc = 1 + buffer[begin+4] * 8;
                    if (len - begin >= zc - 2) {
                        bs = new byte[zc];
                        System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                        beginRef.addAndGet(bs.length+4);
                    }
                }
                break;
            case 213:
                if (len - begin >= 1) {
                    bs = new byte[3];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            case 215:
                if (len >= begin) {
                    bs = new byte[2];
                    System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                    beginRef.addAndGet(bs.length+4);
                }
                break;
            default:
        }

        return dataUnit;
    }

    private RunaFrameSequence.DataUnit structUnitDataOne(byte[] buffer, AtomicInteger beginRef, int len) {
        int begin = beginRef.get();
        if (buffer.length - begin < 6) {
            return null;
        }
        int pn = pn(buffer[begin], buffer[begin+1]);
        int fn = fn(buffer[begin+2], buffer[begin+3]);
        RunaFrameSequence.DataUnit dataUnit = null;
        //根据计算结果，数据长度len和起始点之差应该至少等于数据单元字节数减二
        //起始点的推进长度还是应该为数据单元长度加上四字节的dadt
        switch (fn) {
            case 1:
                if (len - begin >= 30) {
                    byte[] afn09f1 = new byte[32];
                    System.arraycopy(buffer, begin+4, afn09f1, 0, afn09f1.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn09f1);
                    beginRef.addAndGet(32+4);
                }
                break;
            case 2:
                if (len - begin >= 4) {
                    byte[] afn0cf2 = new byte[6];
                    System.arraycopy(buffer, begin+4, afn0cf2, 0, afn0cf2.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf2);
                    beginRef.addAndGet(6+4);
                }
                break;
            case 4:
                if (len - begin >= -1) {
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, new byte[]{buffer[begin+4]});
                    beginRef.addAndGet(1+4);
                }
                break;
            case 10:
            case 12:
                if (len - begin >= 6) {
                    byte[] afn0cf10 = new byte[8];
                    System.arraycopy(buffer, begin+4, afn0cf10, 0, afn0cf10.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf10);
                    beginRef.addAndGet(8+4);
                }
                break;
            case 13:
                if (len - begin >= 2) {
                    byte[] afn0cf13 = new byte[4];
                    System.arraycopy(buffer, begin+4, afn0cf13, 0, afn0cf13.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf13);
                    beginRef.addAndGet(4+4);
                }
                break;
            case 14:
                if (len - begin >= 9) {
                    byte[] afn0cf14 = new byte[11];
                    System.arraycopy(buffer, begin+4, afn0cf14, 0, afn0cf14.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf14);
                    beginRef.addAndGet(9+4);
                }
                break;
            case 129:
                if (len - begin >= 24) {
                    byte[] afn0cf129 = new byte[26];
                    System.arraycopy(buffer, begin+4, afn0cf129, 0, afn0cf129.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf129);
                    beginRef.addAndGet(26+4);
                }
                break;
            case 173:
                if (len - begin >= 23) {
                    byte[] afn0cf173 = new byte[25];
                    System.arraycopy(buffer, begin+4, afn0cf173, 0, afn0cf173.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf173);
                    beginRef.addAndGet(25 + 4);
                }
                break;
            case 174:
                if (len - begin >= 42) {
                    byte[] afn0cf174 = new byte[44];
                    System.arraycopy(buffer, begin+4, afn0cf174, 0, afn0cf174.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf174);
                    beginRef.addAndGet(44 + 4);
                }
                break;
            case 176:
                if (len - begin >= 19) {
                    if ((buffer[begin+11] & 1) == 0) {
                        byte[] afn0cf176 = new byte[21];
                        System.arraycopy(buffer, begin+4, afn0cf176, 0, afn0cf176.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf176);
                        beginRef.addAndGet(21+4);
                    } else if (len - begin >= 19 + 38){
                        byte[] afn0cf176rz = new byte[21 + 38]; //瑞纳智能阀
                        System.arraycopy(buffer, begin+4, afn0cf176rz, 0, afn0cf176rz.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf176rz);
                        beginRef.addAndGet(21+38+4);
                    } else if ((buffer[begin+11] + buffer[begin+12] == -2 && len - begin < 19 + 38)) {
                        byte[] afn0cf176 = new byte[21];
                        System.arraycopy(buffer, begin+4, afn0cf176, 0, afn0cf176.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf176);
                        beginRef.addAndGet(21+4);
                    }
                }
                break;
            case 177:
                if (len - begin >= 57) {
                    byte[] afn0cf177 = new byte[53];
                    System.arraycopy(buffer, begin+4, afn0cf177, 0, afn0cf177.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf177);
                    beginRef.addAndGet(57);
                }
                break;
            case 200:
                if (len - begin >= 90) {
                    if (buffer[begin+9] == 0) {
                        //是否携带额外2个测温点数据
                        if (buffer[begin+10] == 2) {
                            byte[] afn0cf200W2C = new byte[92 + 12]; //温控阀基本数据 + 预留两个测温板
                            System.arraycopy(buffer, begin+4, afn0cf200W2C, 0, afn0cf200W2C.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf200W2C);
                            beginRef.addAndGet(92+32+4);
                        } else if ((buffer[begin+10]>>2&1) == 1) {  //锁闭阀
                            byte[] afn0cf200S = new byte[21];
                            System.arraycopy(buffer, begin+4, afn0cf200S, 0, afn0cf200S.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf200S);
                            beginRef.addAndGet(21+4);
                        } else {
                            byte[] afn0cf200W = new byte[92];       //温控阀基本数据
                            System.arraycopy(buffer, begin+4, afn0cf200W, 0, afn0cf200W.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf200W);
                            beginRef.addAndGet(92+4);
                        }
                    } else if (len - begin >= 90 + 79){
                        //是否携带额外2个测温点数据
                        if (buffer[begin+10] == 2) {
                            byte[] afn0cf200T2C = new byte[92 + 79 + 12]; //温控阀基本数据 + 通断数据预留 + 两个测温板
                            System.arraycopy(buffer, begin+4, afn0cf200T2C, 0, afn0cf200T2C.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf200T2C);
                            beginRef.addAndGet(92+79+32+4);
                        } else {
                            byte[] afn0cf200T = new byte[92 + 79];//温控阀基本数据 + 通断数据
                            System.arraycopy(buffer, begin+4, afn0cf200T, 0, afn0cf200T.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf200T);
                            beginRef.addAndGet(92+79+4);
                        }
                    }
                }
                break;
            case 201:
                if (len - begin >= 29) {
                    byte[] afn0cf201 = new byte[31];
                    System.arraycopy(buffer, begin+4, afn0cf201, 0, afn0cf201.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf201);
                    beginRef.addAndGet(31+4);
                }
                break;
            case 202:
                if (len - begin >= 42 + 21) {
                    byte[] afn0cf202 = new byte[44 + 21];   //热表带档案
                    System.arraycopy(buffer, begin+4, afn0cf202, 0, afn0cf202.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf202);
                    beginRef.addAndGet(44+4+21);
                }
                break;
            case 203:
                if (len - begin >= 23 + 21) {
                    byte[] afn0cf203 = new byte[25 + 21];   //水表带档案
                    System.arraycopy(buffer, begin+4, afn0cf203, 0, afn0cf203.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf203);
                    beginRef.addAndGet(25+4+21);
                }
                break;
            case 204:
                if (len - begin >= 24 + 21) {
                    byte[] afn0cf204 = new byte[26 + 21];   //电表带档案
                    System.arraycopy(buffer, begin+4, afn0cf204, 0, afn0cf204.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf204);
                    beginRef.addAndGet(26+21+4);
                }
                break;
            case 205:
                if (len - begin >= 90 + 21) {
                    if (buffer[begin+9+21] == 0) {
                        //是否携带额外2个测温点数据
                        if (buffer[begin+10+21] == 2) {
                            byte[] afn0cf205W2C = new byte[92 + 21 + 12];//温控阀基本数据带档案 + 预留两个测温板
                            System.arraycopy(buffer, begin+4, afn0cf205W2C, 0, afn0cf205W2C.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf205W2C);
                            beginRef.addAndGet(92+32+21+4);
                        } else {
                            byte[] afn0cf205W = new byte[92 + 21];  //温控阀基本数据带档案
                            System.arraycopy(buffer, begin+4, afn0cf205W, 0, afn0cf205W.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf205W);
                            beginRef.addAndGet(92+21+4);
                        }
                    } else if (len - begin >= 90 + 79 + 21){
                        //是否携带额外2个测温点数据
                        if (buffer[begin+10+21] == 2) {
                            byte[] afn0cf205T2C = new byte[92 + 79 + 21 + 12]; //通断阀带档案 + 预留两个测温板
                            System.arraycopy(buffer, begin+4, afn0cf205T2C, 0, afn0cf205T2C.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf205T2C);
                            beginRef.addAndGet(92+79+32+21+4);
                        } else {
                            byte[] afn0cf200T = new byte[92 + 79];//温控阀基本数据 + 通断数据
                            System.arraycopy(buffer, begin+4, afn0cf200T, 0, afn0cf200T.length);
                            dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf200T);
                            beginRef.addAndGet(92+79+21+4);
                        }
                    }
                }
                break;
            case 206:
                if (len - begin >= 21 + 57) {
                    byte[] afn0cf206 = new byte[53 + 21];
                    System.arraycopy(buffer, begin+4, afn0cf206, 0, afn0cf206.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf206);
                    beginRef.addAndGet(21 + 57);
                }
                break;
            case 207:
                if (len - begin >= 29 + 21) {
                    byte[] afn0cf207 = new byte[31 + 21];
                    System.arraycopy(buffer, begin+4, afn0cf207, 0, afn0cf207.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf207);
                    beginRef.addAndGet(21+31+4);
                }
                break;
            case 208:
                if (len - begin >= 25 + 21) {
                    byte[] bs;
                    if ((buffer[begin+11+21] & 1) == 1 && len - begin >= 63 + 21) {
                        bs = new byte[59+21];
                        System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                        beginRef.addAndGet(63+21);
                    } else {
                        bs = new byte[21+21];
                        System.arraycopy(buffer, begin+4, bs, 0, bs.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, bs);
                        beginRef.addAndGet(25+21);
                    }
                }
                break;
            case 248:
                if (len - begin >= 4) {
                    int l = ByteUtil.byteToShort(buffer, begin+4, ByteOrder.BA).intValue();
                    int l2 = len - begin;
                    if (l2 == l + 2 || l2 == l) {
                        byte[] afn0cf248 = new byte[l];
                        System.arraycopy(buffer, begin + 6, afn0cf248, 0, afn0cf248.length);
                        dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0cf248);
                        beginRef.addAndGet(l + 2);
                    }
                }
                break;
            default:
        }
        return dataUnit;
    }

    private RunaFrameSequence.DataUnit structUnitDataTwo(byte[] buffer, AtomicInteger beginRef, int len) {
        int begin = beginRef.get();
        if (buffer.length - begin < 6) {
            return null;
        }
        int pn = pn(buffer[begin], buffer[begin+1]);
        int fn = fn(buffer[begin+2], buffer[begin+3]);
        RunaFrameSequence.DataUnit dataUnit = null;
        switch (fn) {
            case 49:
            case 53:
                if (len - begin >= 5) {
                    byte[] afn0df49 = new byte[7];
                    System.arraycopy(buffer, begin+4, afn0df49, 0, afn0df49.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df49);
                    beginRef.addAndGet(7+4);
                }
                break;
            case 51:
            case 54:
                if (len - begin >= 4) {
                    byte[] afn0df51 = new byte[6];
                    System.arraycopy(buffer, begin+4, afn0df51, 0, afn0df51.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df51);
                    beginRef.addAndGet(6+4);
                }
                break;
            case 219:
                if (len - begin >= 42 + 3) {
                    byte[] afn0df219 = new byte[3 + 44];
                    System.arraycopy(buffer, begin+4, afn0df219, 0, afn0df219.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df219);
                    beginRef.addAndGet(44+3+4);
                }
                break;
            case 220:
                if (len - begin >= 42 + 2) {
                    byte[] afn0df220 = new byte[2 + 44];
                    System.arraycopy(buffer, begin+4, afn0df220, 0, afn0df220.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df220);
                    beginRef.addAndGet(44+2+4);
                }
                break;
            case 225:
                if (len - begin >= 42 + 4) {
                    byte[] afn0df225 = new byte[4 + 44];
                    System.arraycopy(buffer, begin+4, afn0df225, 0, afn0df225.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df225);
                    beginRef.addAndGet(44+4+4);
                }
                break;
            case 227:
                if (len - begin >= 42 + 21 + 3) {
                    byte[] afn0df227 = new byte[3 + 21 + 44];
                    System.arraycopy(buffer, begin+4, afn0df227, 0, afn0df227.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df227);
                    beginRef.addAndGet(7 + 21 + 44);
                }
                break;
            case 228:
                if (len - begin >= 42 + 21 + 2) {
                    byte[] afn0df228 = new byte[2 + 21 + 44];
                    System.arraycopy(buffer, begin+4, afn0df228, 0, afn0df228.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df228);
                    beginRef.addAndGet(6 + 21 + 44);
                }
                break;
            case 229:
                if (len - begin >= 42 + 21 + 4) {
                    byte[] afn0df229 = new byte[4 + 21 + 44];
                    System.arraycopy(buffer, begin+4, afn0df229, 0, afn0df229.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df229);
                    beginRef.addAndGet(8 + 21 + 44);
                }
                break;
            case 230:
                if (len - begin >= 23 + 21 + 3) {
                    byte[] afn0df230 = new byte[3 + 21 + 25];
                    System.arraycopy(buffer, begin+4, afn0df230, 0, afn0df230.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df230);
                    beginRef.addAndGet(7 + 21 + 25);
                }
                break;
            case 231:
                if (len - begin >= 23 + 21 + 2) {
                    byte[] afn0df231 = new byte[2 + 21 + 25];
                    System.arraycopy(buffer, begin+4, afn0df231, 0, afn0df231.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df231);
                    beginRef.addAndGet(6 + 21 + 25);
                }
                break;
            case 232:
                if (len - begin >= 23 + 21 + 4) {
                    byte[] afn0df232 = new byte[4 + 21 + 25];
                    System.arraycopy(buffer, begin+4, afn0df232, 0, afn0df232.length);
                    dataUnit = new RunaFrameSequence.DataUnit(pn, fn, afn0df232);
                    beginRef.addAndGet(8 + 21 + 25);
                }
                break;
            default:
        }
        return dataUnit;
    }


    public static void main(String[] args) {
        RunaICAnalysis analysis = new RunaICAnalysis(new RunaEquDataAnalysis());
//        byte[] bytes = ByteUtil.hexStringToByte("68 BE 00 BE 00 68 88 15 64 4B 00 00 10 60 00 00 01 00 02 20 00 68 28 00 69 70 71 50 68 91 14 33 32 34 33 C3 59 39 33 33 33 33 33 33 33 33 33 33 33 33 33 EF 16 D3 16");
//        byte[] bytes = ByteUtil.hexStringToByte("683200320068C96810E502000270000001009B16");


//        byte[] bytes = ByteUtil.hexStringToByte("68 42 00 42 00 68 88 34 12 02 00 02 0A 60 00 00 40 17 18 00 0A 00 B5 16".trim());
//        byte[] bytes = ByteUtil.hexStringToByte("68 CE 02 CE 02 68 88 15 64 62 01 02 0C 60 00 20 80 18 17 10 19 07 23 00 00 00 00 00 00 23 FA 00 00 00 00 00 00 00 1E 00 00 00 00 00 00 00 64 00 64 00 00 25 00 05 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 45 33 11 20 01 15 00 00 64 00 00 00 00 00 00 7F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 16".trim());
//        String s = "68F200F20068887632214E020C60100120154100026110111809240000000000544878000000000000000094964808102400001524000007380200121018092400000016";
//        String s = "000000160000000000000000000000C31668F601F601688801257037020C603030101912042AFFFFFFFFFFFF010000000000000000005C001117030B18000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000362916060424800064000000000000000000000000000000000000000000000000000000B816  ";
//        String s = "68E200E200688826732301020C60040D2015010322012300000000000000000000000000000000000000000000000000000000000000000000000000FFFF4116  ";
//        String s = "37000272000008001600000222041124000000000B000000000000000000000095166836013601688801257537020C600101021912042A913249041332010000000000000000002C0002220411240052890400528904530300003700000039555100523800003230000039120146372104112400003D16  ";
//        String s = "68E200E20068887612754E020C604007201520002011240000000060610900100100002300000054840000612900001334000039000124090020112400009516";

        RequestPendingTask.addTask("145800984", new RequestPendingTask(TaskTypeEnum.READ_RN_MODBUS_VALVE, Valve.getValve(CommValve.builder().sequence(196).build())));
        String s = "685A005A0068885814D80300106000000100040700C40302005475AA8716";
        System.out.println(s.length());
        byte[] bytes =  ByteUtil.hexStringToByte(s);
        analysis.fill(bytes, bytes.length,"145800984");
        IInterData gain = analysis.gain();
        System.out.println(JSON.toJSONString(gain));
    }

}
